#include <iostream>
using namespace std;
#include <string>
#include <vector>
#include <list>
#include <set>
#include <algorithm>
#include <functional>

template <typename T>
class ShowElement
{
public:
        ShowElement()
        {
                n = 0;
        }
        void operator()(T &t)
        {
                cout<<t<<" ";
        }
        void printN()
        {
                n++;
                cout<<"n: "<<n<<endl;
        }
private:
        int n;
};

//plus<int> 预定义好的函数对象。能实现不同类型的数据的 + 运算
//实现了 数据类型 和 算法的分离 ===》通过函数对象技术实现的....

//思考:怎么样知道 plus<type> 是两个参数
void test1()
{
        plus<int> intAdd;
        int x = 10, y = 20;
        int z = intAdd(x,y);
        cout<<"z:"<<z<<endl;

        plus<string> stringAdd;
        string s1 = "aaa";
        string s2 = "bbb";
        string s3 = stringAdd(s1, s2);
        cout<<"s3:"<<s3<<endl;

        vector<string> v1;
        v1.push_back("bbb");
        v1.push_back("aaa");
        v1.push_back("ccc");
        v1.push_back("zzz");
        v1.push_back("ccc");

        sort(v1.begin(), v1.end(), greater<string>());

        for_each(v1.begin(), v1.end(), ShowElement<string>());
        cout<<endl;

        //求ccc出现的次数
        string sc = "ccc";
        //equal_to<string>()函数对象 有两个参数 left参数来自容器 right参数来自sc
        //      需要通过bind2nb适配器 : 把预定义函数对象 和 第二个参数进行绑定
        int num = count_if(v1.begin(), v1.end(), bind2nd(equal_to<string>(), sc));
        cout<<"ccc 出现的次数: "<<num<<endl;
}

class IsGreat
{
public:
        IsGreat(int i){
                m_num = i;
        }
        bool operator()(int &num){
                if(num > m_num){
                        return true;
                }
                return false;
        }
private:
        int m_num;
};

void test2()
{
        vector<int> v1;
        for (int i = 0; i < 10; i++){
                v1.push_back(i+1);
        }
        
        for_each(v1.begin(), v1.end(), ShowElement<int>());
        cout<<endl;

        int num1 = count(v1.begin(), v1.end(), 3);
        cout<<"容器中元素3的个数: "<<num1<<endl;

        //通过 谓词 求大于2的格式
        int num2 = count_if(v1.begin(), v1.end(), IsGreat(2));
        cout<<"容器中元素大于2的个数: "<<num2<<endl;

        //通过 预定义的函数对象 求大于2的格式
        //greater<int>()有两个参数 做参数来自容器的元素,右参数固定成2(通过bind2and做的)
        int num3 = count_if(v1.begin(), v1.end(), bind2nd(greater<int>(),2));
        cout<<"容器中元素大于2的个数: "<<num3<<endl;

        //求奇数的个数
        int num4 = count_if(v1.begin(), v1.end(), bind2nd(modulus<int>(), 2));
        cout<<"容器中元素是奇数的个数: "<<num4<<endl;

        //求偶数的个数
        int num5 = count_if(v1.begin(), v1.end(), not1( bind2nd(modulus<int>(), 2)));
        cout<<"容器中元素是偶数的个数: "<<num5<<endl;
}

int main(int argc, char const *argv[])
{
        //test1();
        test2();
        return 0;
}
